﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using LanguagePolish.EntityModel;

namespace LanguagePolish.Models
{
    public class GradesModel
    {
        public DataTable Grades { get; private set; }

        public Class Class { get; private set; }

        private readonly Dictionary<Student, DataColumn> studCols = new Dictionary<Student, DataColumn>();
        private readonly Dictionary<DataColumn, Student> colsStud = new Dictionary<DataColumn, Student>();

        public GradesModel(Class myClass)
        {
            Class = myClass;
            CreateGrid();
        }

        /// <summary>
        /// Отмапливает ентити в ДатаГрид
        /// </summary>
        private void CreateGrid()
        {
            DataTable dt = new DataTable("Grades");
            var students = Class.Students.OrderBy(s => s.Name).ToList();
            dt.Columns.Add("Lesson", typeof(Lesson));       // Первая колонка фейковая - Lesson
            dt.Columns.Add("Date", typeof (DateTime));      // Дата
            foreach (var stud in students)
            {
                // Попарно: оценка студента(число) и объект Grade
                DataColumn col = dt.Columns.Add(stud.Name, typeof(object));
                dt.Columns.Add(stud.Name + "_GRADE", typeof(Grade));
                studCols.Add(stud, col);
                colsStud.Add(col, stud);
            }
            // добавляем строки - уроки
            var lessons = Class.Lessons.OrderBy(l => l.LessonDate).ToList();
            foreach (var less in lessons)
            {
                var row = dt.NewRow();
                row[0] = less;
                row[1] = less.LessonDate;
                var grades = less.Grades.ToList();
                foreach (var grad in grades)
                {
                    var stud = grad.Student;
                    var val = grad.GradeValue;
                    DataColumn col = studCols[stud];
                    int colIndex = dt.Columns.IndexOf(col);
                    row[colIndex] = val;
                    row[colIndex + 1] = grad;
                }
                dt.Rows.Add(row);
            }
            dt.ColumnChanging += dt_ColumnChanging;
            Grades = dt;
        }

        /// <summary>
        /// Синхронизирует Дата тейбл с Entity. Заодно и валидирует.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void dt_ColumnChanging(object sender, DataColumnChangeEventArgs e)
        {
            var context = LinksProvider.Model.EntityContext;
            Lesson lesson = (Lesson)e.Row[0];
            int colIndex = Grades.Columns.IndexOf(e.Column);
            Grade grade = e.Row[colIndex + 1] as Grade;
            int? gradeValue = null;
            int gradeVal;
            if (int.TryParse(e.ProposedValue.ToString(), out gradeVal))
            {
                GradeValidationCut(ref gradeVal);
                gradeValue = gradeVal;
            }
            e.ProposedValue = gradeValue;
            // новое значение либо записываем в существующую Grade либо создаем новый обьект.
            if (grade != null)
            {
                grade.GradeValue = gradeValue;
            }
            else
            {
                grade = new Grade
                {
                    Lesson = lesson,
                    Student = colsStud[e.Column],
                    GradeValue = gradeValue
                };
                lesson.Grades.Add(grade);
            }
            context.SaveChanges();
            lesson.Class.NotifyAll();
        }
        
        private void GradeValidationCut(ref int val)
        {
            if (val < 0)
                val = 0;
            if (val > 100)
                val = 100;
        }
    }
}
